from datetime import datetime
from typing import Literal, Optional

from pydantic import Field, field_serializer, field_validator

from src.models.base import IdenticalModel
from src.utils.date_utils import parse_date


class BenkeRecord(IdenticalModel):
    id: str = Field(
        title="学号",
        min_length=1,
        description="学号，不允许为空",
        serialization_alias="学号",
    )
    name: str = Field(
        title="姓名",
        min_length=1,
        description="姓名，不允许为空",
        serialization_alias="姓名",
    )
    education_level: Literal["本科"] = Field(
        title="培养层次",
        default="本科",
        description="培养层次，只能为“本科”",
        serialization_alias="培养层次",
    )
    learning_mode: Literal["全日制", "非全日制"] = Field(
        title="学习方式",
        description="学习方式，只能为“全日制”或“非全日制”",
        serialization_alias="学习方式",
    )
    college: str = Field(title="学院", serialization_alias="学院")

    major: str = Field(title="专业", serialization_alias="专业")
    class_name: str = Field(title="班级名称", serialization_alias="班级名称")
    class_number: str = Field(title="班号", serialization_alias="班号")
    is_international_student: Literal["是", "否"] = Field(
        title="是否留学生",
        default="否",
        description="是否留学生，只能为“是”或“否”",
        serialization_alias="是否留学生",
    )

    is_hac_student: Literal["是", "否"] = Field(
        title="是否港澳台学生",
        default="否",
        description="是否港澳台学生，只能为“是”或“否”",
        serialization_alias="是否港澳台学生",
    )
    phone_number: str = Field(title="联系电话", serialization_alias="联系电话")

    record_status: str = Field(title="学籍最后状态", serialization_alias="学籍最后状态")

    political_status: str = Field(title="政治面貌", serialization_alias="政治面貌")
    id_card_number: str = Field(title="证件号码", serialization_alias="证件号码")

    archive_arrvial_status: Literal["已到档", "未到档", ""] = Field(
        title="到档情况",
        default="未到档",
        description="到档情况，只能为“已到档”、“未到档”或留空",
        serialization_alias="到档情况",
    )
    archive_arrvial_time: Optional[datetime] = Field(title="到档时间", default=None)
    party_archive_lend_record: str = Field(
        title="党员档案借出情况记录",
        default="",
        serialization_alias="党员档案借出情况记录",
    )

    degree_archive_status: Literal["已归档", "未归档", ""] = Field(
        title="学位档案归档状态",
        default="",
        description="学位档案归档状态，只能为“已归档”、“未归档”或留空",
        serialization_alias="档案归档状态",
    )
    graduate_registration_form_status: Literal["已归档", "未归档", ""] = Field(
        title="毕业登记表状态",
        default="",
        description="毕业登记表状态，只能为“已归档”、“未归档”或留空",
        serialization_alias="毕业登记表状态",
    )
    transcript_status: Literal["已归档", "未归档", ""] = Field(
        title="成绩单状态",
        default="",
        description="成绩单状态，只能为“已归档”、“未归档”或留空",
        serialization_alias="成绩单状态",
    )
    graduation_status: Literal["毕业", "在读", "肄业", "结业", "退学", ""] = Field(
        title="毕业状态",
        default="在读",
        description="毕业状态，只能为“毕业”、“在读”、“肄业”、“结业”、“退学”或留空",
        serialization_alias="毕业状态",
    )
    archive_delivery_status: Literal["已寄出", "未寄出", ""] = Field(
        title="档案寄出情况",
        default="未寄出",
        description="档案寄出情况，只能为“已寄出”、“未寄出”或留空",
        serialization_alias="档案寄出情况",
    )

    @field_serializer("archive_arrvial_time")
    def format_archive_arrvial_time(self, v: Optional[datetime]):
        if v is None:
            return None
        return v.strftime("%Y-%m-%d")

    @field_validator("archive_arrvial_time", mode="before")
    def parse_archive_arrvial_time(cls, v):
        if isinstance(v, str):
            return parse_date(v)
        return v

    @classmethod
    def _validate_party_archive_lend_record(cls, s: str):
        """验证党员档案借出情况记录格式"""
        s = s.strip()
        if s == "":
            return s  # 空字符串是允许的

        # 检查基本格式：必须有分号分隔
        if ";" not in s:
            raise ValueError("党员档案借出情况记录格式错误：必须包含分号分隔符")

        parts = [p.strip() for p in s.split(";") if p.strip()]
        if len(parts) < 2:
            raise ValueError("党员档案借出情况记录格式错误：至少需要状态和一条记录")

        # 验证状态部分
        head = parts[0]
        if head not in ["已就绪", "未就绪"]:
            raise ValueError(
                f"党员档案借出情况记录状态错误：'{head}'，必须是'已就绪'或'未就绪'"
            )

        # 验证每条记录
        for i, seg in enumerate(parts[1:], 1):
            try:
                dt_str, name, action = seg.split(" ")
                # 验证时间格式
                datetime.strptime(dt_str, "%Y-%m-%d-%H:%M:%S")
                # 验证操作类型
                if action not in ["借出", "归还"]:
                    raise ValueError(f"操作类型错误：'{action}'，必须是'借出'或'归还'")
            except ValueError as e:
                if "unpack" in str(e):
                    raise ValueError(
                        f"记录格式错误：第{i}条记录'{seg}'，格式应为'时间 姓名 操作'"
                    )
                elif "does not match format" in str(e):
                    raise ValueError(
                        f"时间格式错误：第{i}条记录的时间'{dt_str}'，格式应为'YYYY-MM-DD-HH:MM:SS'"
                    )
                else:
                    raise e

        return s

    @field_validator("party_archive_lend_record", mode="before")
    def parse_party_archive_lend_record(cls, s: str):
        return cls._validate_party_archive_lend_record(s)


if __name__ == "__main__":
    instance = BenkeRecord(
        id="123456",
        name="张三",
        education_level="本科",
        learning_mode="全日制",
        college="学院",
        major="专业",
        class_name="班级",
        class_number="班号",
        is_international_student="否",
        is_hac_student="否",
        phone_number="12345678901",
        record_status="正常",
        political_status="群众",
        id_card_number="44010119900101001X",
        graduation_status="毕业",
        archive_arrvial_status="未到档",
        archive_arrvial_time=datetime(2023, 1, 1),
        party_archive_lend_record=(
            "已就绪; 2025-10-28-10:11:46 张三 借出; 2025-10-28-10:11:46 李四 归还; 2025-10-28-10:11:46 王五 借出"
        ),
        archive_delivery_status="已寄出",
        create_time=datetime.now(),
        last_modified_time=datetime.now(),
    )
    # data = instance.model_dump()
    # data["party_archive_lend_record"] = "!11"
    setattr(instance, "party_archive_lend_record", "!11")
    instance.model_validate(instance)
